<html>
<head><meta charset="utf-8"><title>Best ways to represent group membership in rust · general · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/index.html">general</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust.html">Best ways to represent group membership in rust</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="228408120"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Best%20ways%20to%20represent%20group%20membership%20in%20rust/near/228408120" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Oliver E. Anderson <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust.html#228408120">(Mar 02 2021 at 13:23)</a>:</h4>
<p>Dear all,<br>
I would like to represent the concept of a class of students in rust. Say I have a struct Student and a struct Class. Each class should be able to tell you which students belong to it and vise versa each student should be able to tell you which class it belongs to. I am relatively new to rust, so any advice on how to go about this would be highly appreciated. I am thinking that lifetimes can make this a demanding task for a novice rustacean, but a very satisfying one for someone more experienced?</p>



<a name="228410282"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Best%20ways%20to%20represent%20group%20membership%20in%20rust/near/228410282" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> kev <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust.html#228410282">(Mar 02 2021 at 13:39)</a>:</h4>
<p>You could possibly introduce an intermediate structure like <code>School</code> which will keep this information?</p>



<a name="228410431"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Best%20ways%20to%20represent%20group%20membership%20in%20rust/near/228410431" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Laurențiu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust.html#228410431">(Mar 02 2021 at 13:40)</a>:</h4>
<p>Try to treat it like a relational database: put the students and classes in <code>Vec</code>s, give them identifiers and use those to make associations</p>



<a name="228411110"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Best%20ways%20to%20represent%20group%20membership%20in%20rust/near/228411110" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> kev <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust.html#228411110">(Mar 02 2021 at 13:44)</a>:</h4>
<p>If the Students and Classes are storing the associations, then if a class is removed, I think you'd need to find all students in that class and remove the class from the students _list_?</p>



<a name="228411223"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Best%20ways%20to%20represent%20group%20membership%20in%20rust/near/228411223" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> kev <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust.html#228411223">(Mar 02 2021 at 13:45)</a>:</h4>
<p>To me, it seems it is better to store the many to many relationship in a separate structure. I have not done database based things in Rust, so I might be off the mark here</p>



<a name="228411260"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Best%20ways%20to%20represent%20group%20membership%20in%20rust/near/228411260" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Oliver E. Anderson <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust.html#228411260">(Mar 02 2021 at 13:45)</a>:</h4>
<p>A friend of mine suggested using HashSet's. Could that maybe work? <a href="https://doc.rust-lang.org/std/collections/struct.HashSet.html">https://doc.rust-lang.org/std/collections/struct.HashSet.html</a></p>



<a name="228411734"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Best%20ways%20to%20represent%20group%20membership%20in%20rust/near/228411734" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> kev <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust.html#228411734">(Mar 02 2021 at 13:48)</a>:</h4>
<p>Something like this was what I was thinking</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="cp">#[derive(Copy, Clone)]</span><span class="w"></span>
<span class="k">struct</span> <span class="nc">Student</span><span class="p">(</span><span class="kt">u32</span><span class="p">);</span><span class="w"></span>

<span class="cp">#[derive(Copy, Clone)]</span><span class="w"></span>
<span class="k">struct</span> <span class="nc">Class</span><span class="p">(</span><span class="kt">u32</span><span class="p">);</span><span class="w"></span>

<span class="k">struct</span> <span class="nc">School</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">students</span><span class="w"> </span>: <span class="nb">Vec</span><span class="o">&lt;</span><span class="n">Student</span><span class="o">&gt;</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="n">classes</span><span class="w"> </span>: <span class="nb">Vec</span><span class="o">&lt;</span><span class="n">Class</span><span class="o">&gt;</span><span class="p">,</span><span class="w"></span>

<span class="w">    </span><span class="c1">// add hashmap to associations</span>
<span class="p">}</span><span class="w"></span>

<span class="k">impl</span><span class="w"> </span><span class="n">School</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">add_student</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">Student</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">student_number</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="bp">self</span><span class="p">.</span><span class="n">students</span><span class="p">.</span><span class="n">len</span><span class="p">();</span><span class="w"></span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">student</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Student</span><span class="p">(</span><span class="n">student_number</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="bp">self</span><span class="p">.</span><span class="n">students</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">student</span><span class="p">);</span><span class="w"></span>
<span class="w">        </span><span class="n">student</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">add_class</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">)</span><span class="w"> </span>-&gt; <span class="nc">Class</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="sd">/// Same as student</span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">  </span><span class="k">pub</span><span class="w"> </span><span class="k">fn</span> <span class="nf">add_student_to_class</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="bp">self</span><span class="p">,</span><span class="w"> </span><span class="n">student_id</span><span class="w"> </span>: <span class="nc">Student</span><span class="p">,</span><span class="w"> </span><span class="n">class_id</span><span class="w"> </span>: <span class="nc">Class</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">      </span><span class="c1">// Add to HashMap or however you store associations</span>
<span class="w">  </span><span class="p">}</span><span class="w"></span>


<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="228411971"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Best%20ways%20to%20represent%20group%20membership%20in%20rust/near/228411971" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> kev <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust.html#228411971">(Mar 02 2021 at 13:50)</a>:</h4>
<p><span class="user-mention silent" data-user-id="390743">Oliver E. Anderson</span> <a href="#narrow/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust/near/228411260">said</a>:</p>
<blockquote>
<p>A friend of mine suggested using HashSet's. Could that maybe work? <a href="https://doc.rust-lang.org/std/collections/struct.HashSet.html">https://doc.rust-lang.org/std/collections/struct.HashSet.html</a></p>
</blockquote>
<p>Yeah I think you can use a HashSet instead of a vector, since you don't want to add the same student twice. It should not be likely, but bugs can happen</p>



<a name="228413791"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Best%20ways%20to%20represent%20group%20membership%20in%20rust/near/228413791" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust.html#228413791">(Mar 02 2021 at 14:02)</a>:</h4>
<p>More importantly, you will need a hashset or similar data structure if you want to be able to remove students and/or use identifiers that don't match insertion order</p>



<a name="228428846"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Best%20ways%20to%20represent%20group%20membership%20in%20rust/near/228428846" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Thom Chiovoloni <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust.html#228428846">(Mar 02 2021 at 15:30)</a>:</h4>
<blockquote>
<p>More importantly, you will need a hashset or similar data structure if you want to be able to remove students and/or use identifiers that don't match insertion order</p>
</blockquote>
<p>Hm? HashSet is totally unordered. Vec is better if you care about ordering, just insertion is O(n). Removal has the same tradeoffs — order-preserving O(n) or unordered swap_remove in O(1).</p>
<p>You could use BTreeSet if you're willing to implement an Ord for students, but if you need access to external data (say: their name) it might be a pain.</p>



<a name="228468724"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Best%20ways%20to%20represent%20group%20membership%20in%20rust/near/228468724" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> The 8472 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust.html#228468724">(Mar 02 2021 at 19:18)</a>:</h4>
<p>There are crates for insertion-ordered sets</p>



<a name="228564447"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Best%20ways%20to%20represent%20group%20membership%20in%20rust/near/228564447" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust.html#228564447">(Mar 03 2021 at 09:57)</a>:</h4>
<p>If the <code>School</code> has enough <code>Student</code>s per <code>Class</code> for <code>HashSet</code> to beat <code>Vec</code>, then the <code>School</code> is in a lot of trouble <span aria-label="big smile" class="emoji emoji-1f604" role="img" title="big smile">:big_smile:</span></p>



<a name="228566976"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Best%20ways%20to%20represent%20group%20membership%20in%20rust/near/228566976" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust.html#228566976">(Mar 03 2021 at 10:15)</a>:</h4>
<p><span class="user-mention silent" data-user-id="209168">Thom Chiovoloni</span> <a href="#narrow/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust/near/228428846">said</a>:</p>
<blockquote>
<blockquote>
<p>More importantly, you will need a hashset or similar data structure if you want to be able to remove students and/or use identifiers that don't match insertion order</p>
</blockquote>
<p>Hm? HashSet is totally unordered. Vec is better if you care about ordering, just insertion is O(n). Removal has the same tradeoffs — order-preserving O(n) or unordered swap_remove in O(1).</p>
</blockquote>
<p>I said you should use HashSet if you <em>aren't</em> using insertion order. For example, if the IDs are already given, for example because they are primary keys in an external database, then you would use a HashSet to hash the keys, and you don't get any ordering. If you don't care to control the identity of the IDs, you can use Vec if you don't need deletion and Slab if you do. (If the data set is small enough, Vec is probably the best choice regardless of whether you need deletion, as <span class="user-mention silent" data-user-id="232018">Daniel Henry-Mantilla</span> says.)</p>



<a name="228571474"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Best%20ways%20to%20represent%20group%20membership%20in%20rust/near/228571474" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Oliver E. Anderson <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Best.20ways.20to.20represent.20group.20membership.20in.20rust.html#228571474">(Mar 03 2021 at 10:44)</a>:</h4>
<p>How does HashSet.replace compare to Vec.insert in terms of  performance?</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>